package com.blkan.calculator.fragments;

import android.content.res.Configuration;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.view.MenuProvider;
import androidx.lifecycle.ViewModelProvider;

import com.blkan.calculator.Calculator;
import com.blkan.calculator.MainActivity;
import com.blkan.calculator.R;
import com.blkan.calculator.databinding.FragmentCalculatorBinding;
import com.blkan.calculator.history.HistoryItem;
import com.blkan.calculator.history.HistoryRepository;
import com.blkan.calculator.util.Input;
import com.blkan.calculator.util.SqliteHelper;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CalculatorFragment extends BasicFragment{
    FragmentCalculatorBinding binding;
    CalculatorViewModel vm;

    @Override
    public int getLayoutResId() {
        return R.layout.fragment_calculator;
    }

    @Override
    public void initView(View rootView) {
        binding = FragmentCalculatorBinding.bind(rootView);
        vm = new ViewModelProvider(this).get(CalculatorViewModel.class);
        if(getArguments() != null)
        {
            HistoryFragmentArgs args = HistoryFragmentArgs.fromBundle(getArguments());
            vm.setInput(new StringBuilder(args.getHistoryItem().getInput()));
            vm.setResult(args.getHistoryItem().getAns());
        }
        binding.tvInput.setText(vm.getInput().toString());
        binding.tvAnswer.setText(vm.getResult());
        initButtons();
        binding.tvInput.setOnClickListener(view ->
        {
            if(getActivity() instanceof MainActivity)
            {
                MainActivity activity = (MainActivity) getActivity();
                int actionId = R.id.action_dest_calculator_fragment_to_dest_history_fragment;
                activity.getNavHostFragment().getNavController().navigate(actionId);
            }
        });
    }


    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }


    private void initButtons() {
        int orientation = getResources().getConfiguration().orientation;
        boolean portrait = orientation == Configuration.ORIENTATION_PORTRAIT;
        binding.btnAc.setOnClickListener(view -> {

            vm.setInput(new StringBuilder(""));
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnBack.setOnClickListener(view -> {
            if (vm.getInput().length() == 0)
                return;
            int cut = backSpace();
            vm.getInput().delete(vm.getInput().length() - cut, vm.getInput().length());
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnPi.setOnClickListener(view -> {
            vm.getInput().append("π");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnAdd.setOnClickListener(view -> {
            addSign("+");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btn7.setOnClickListener(view -> {
            addNumber(7);
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btn8.setOnClickListener(view -> {
            addNumber(8);
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btn9.setOnClickListener(view -> {
            addNumber(9);
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnMinus.setOnClickListener(view ->
        {
            addSign("-");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btn4.setOnClickListener(view -> {
            addNumber(4);
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btn5.setOnClickListener(view -> {
            addNumber(5);
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btn6.setOnClickListener(view -> {
            addNumber(6);
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnMultiply.setOnClickListener(view ->
        {
            addSign("×");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btn1.setOnClickListener(view -> {
            addNumber(1);
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btn2.setOnClickListener(view -> {
            addNumber(2);
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btn3.setOnClickListener(view -> {
            addNumber(3);
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnDivide.setOnClickListener(view ->
        {
            addSign("÷");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnAns.setOnClickListener(view -> {
            vm.getInput().append("Ans");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btn0.setOnClickListener(view -> {
            addNumber(0);
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnPoint.setOnClickListener(view -> {
            if (vm.getInput().length() == 0)
                vm.getInput().append(0);
            char c = vm.getInput().charAt(vm.getInput().length() - 1);
            if (c >= '0' && c <= '9') {
                vm.getInput().append(".");
                binding.tvInput.setText(vm.getInput().toString());
            }
        });
        binding.btnEqual.setOnClickListener(view -> {
            String s = vm.getInput().toString();
            String ans = vm.getResult();
            String input = vm.getInput().toString();
            Pattern pattern = Pattern.compile("×");
            Matcher matcher = pattern.matcher(s);
            s = matcher.replaceAll("*");

            pattern = Pattern.compile("÷");
            matcher = pattern.matcher(s);
            s = matcher.replaceAll("/");

            pattern = Pattern.compile("(?<=\\A|\\+|-|\\*|\\/|\\^)(Ans)");
            matcher = pattern.matcher(s);
            s = matcher.replaceAll('(' + vm.getResult() + ')');

            pattern = Pattern.compile("Ans");
            matcher = pattern.matcher(s);
            s = matcher.replaceAll("*" + '(' + vm.getResult() + ')');

            String result = Calculator.getInstance().calExpression(s, vm.isDeg(), false);
            if(result.contains("错"))
            {
                Toast.makeText(getContext(), result, Toast.LENGTH_LONG).show();
            }else {
                vm.setResult(result);
                if (vm.getResult().endsWith(".0"))
                    vm.setResult(vm.getResult().substring(0, vm.getResult().length() - 2));
                binding.tvAnswer.setText(vm.getResult());
                HistoryItem historyItem = new HistoryItem(ans, input, vm.getResult());
                SqliteHelper helper = new SqliteHelper(getContext());
                helper.insert(historyItem);
            }
        });
        if (portrait)
            return;
        if (vm.isDeg())
            binding.btnRad.setText("Deg");
        binding.btnRad.setOnClickListener(view -> {
            vm.setDeg(!vm.isDeg());
            if (vm.isDeg())
                binding.btnRad.setText("Deg");
            else
                binding.btnRad.setText("Rad");
        });
        binding.btnLeftP.setOnClickListener(view -> {
            if (vm.getInput().length() != 0) {
                char c = vm.getInput().charAt(vm.getInput().length() - 1);
                if ((c >= '0' && c <= '9') || c == ')' || c == 'e' || c == 'π' || c == 's' || c == '!') {
                    vm.getInput().append("×");
                }
            }
            vm.getInput().append('(');
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnRightP.setOnClickListener(view -> {
            if (vm.getInput().length() != 0) {
                vm.getInput().append(')');
                binding.tvInput.setText(vm.getInput().toString());
            }
        });
        binding.btnSin.setOnClickListener(view -> {
            vm.getInput().append("sin(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnCos.setOnClickListener(view -> {
            vm.getInput().append("cos(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnTan.setOnClickListener(view -> {
            vm.getInput().append("tan(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnArcsin.setOnClickListener(view -> {
            vm.getInput().append("arcsin(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnArccos.setOnClickListener(view -> {
            vm.getInput().append("arccos(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnArctan.setOnClickListener(view -> {
            vm.getInput().append("arctan(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnLg.setOnClickListener(view -> {
            vm.getInput().append("lg(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnLg.setOnClickListener(view -> {
            vm.getInput().append("lg(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnLn.setOnClickListener(view -> {
            vm.getInput().append("ln(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnE.setOnClickListener(view -> {
            vm.getInput().append('e');
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnPow.setOnClickListener(view -> {
            addSign("^(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnSqrt.setOnClickListener(view -> {
            vm.getInput().append("sqrt(");
            binding.tvInput.setText(vm.getInput().toString());
        });
        binding.btnFact.setOnClickListener(view -> {
            if (vm.getInput().length() == 0)
                return;
            char c = vm.getInput().charAt(vm.getInput().length() - 1);
            if (c == '(' || c == '!')
                return;
            if (c == '+' || c == '-' || c == '×' || c == '÷') {
                vm.getInput().deleteCharAt(vm.getInput().length() - 1);
            }
            vm.getInput().append('!');
            binding.tvInput.setText(vm.getInput().toString());
        });
    }

    private void addNumber(int number) {
        if (vm.getInput().length() != 0) {
            char c = vm.getInput().charAt(vm.getInput().length() - 1);
            if (c == ')' || c == 'e' || c == 'π' || c == 's' || c == '!') {
                vm.getInput().append("×");
            }
        }
        vm.getInput().append(number);
    }

    private void addSign(String sign) {
        if (vm.getInput().length() == 0)
            vm.getInput().append(0);
        else {
            char c = vm.getInput().charAt(vm.getInput().length() - 1);
            if (c == '+' || c == '-' || c == '×' || c == '÷') {
                vm.getInput().deleteCharAt(vm.getInput().length() - 1);
            }
        }
        vm.getInput().append(sign);
    }


    /**
     * 获取应该退多少个字符
     * @return
     */
    private int backSpace() {
        String s = vm.getInput().toString();
        if (s.endsWith("^("))
            return 2;
        if (s.endsWith("lg(") || s.endsWith("ln(") || s.endsWith("Ans"))
            return 3;
        if (s.endsWith("sin(") || s.endsWith("cos(") || s.endsWith("tan("))
            return 4;
        if (s.endsWith("sqrt("))
            return 5;
        if (s.endsWith("arcsin(") || s.endsWith("arccos(") || s.endsWith("arctan("))
            return 7;
        return 1;
    }


}

